package com.gitee.wsl.security.encrypt.sample

import com.gitee.wsl.security.encrypt.Encrypt
import com.gitee.wsl.security.encrypt.StringToStringEncrypt


/** refer http://www.practicalcryptography.com/ciphers/classical-era/bifid/ */
class Bifid(val key: String, val period: Int = 1) :StringToStringEncrypt{

    override fun encrypt(src: String): String =
        src.bifid(key,period)

    override fun decrypt(src: String): String =
        src.bifidDecrypt(key,period)
}

fun Encrypt.Companion.bifid(key: String, period: Int = 1) = Bifid(key, period)

internal fun String.bifid(key: String, period: Int = 1) =
    filter { it.isLetter() }
        .polybius(key)
        .chunked(period * 2)
        .joinToString("") {
            it.filterIndexed { index, _ -> index % 2 == 0 } +
                    it.filterIndexed { index, _ -> index % 2 == 1 }
        }
        .polybiusDecrypt(key)

internal fun String.bifidDecrypt(key: String, period: Int = 1) =
    filter { it.isLetter() }
        .polybius(key)
        .chunked(period * 2)
        .joinToString("") {
            it.foldIndexed(CharArray(it.length)) { index, acc, c ->
                acc.apply {
                    if (index < this.size / 2) {
                        this[index * 2] = c
                    } else {
                        this[(index - this.size / 2) * 2 + 1] = c
                    }
                }
            }
                .joinToString("")
        }
        .polybiusDecrypt(key)
